home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * *
- * CheMnimaTe to Animate Chemical Reactions *
- * *
- * *
- * this program is written to show how molecules *
- * are in 3-d and how mechanisms work. *
- * *
- * *
- * *
- * *
- *==============================================================*
- *Vers. Date Author Comment *
- *sk1 22Mar91 KvGend started working on it. *******
- *sk5 24Mar91 KvGend is now able to rotate some complicated formula*
- *sk9 30Mar91 KvGend Now accepts scripts. Is able to play *******
- * along with penicilline *
- *ch6 09Apr91 KvGend Scripts now use full commands. *
- *pars6 08May91 KvGend Tokenized the whole stuff. code cleanup, *
- * but the code became longer (who cares?) *
- *pars7 02Jun91 KvGend Now accepts expressions!!! *
- * And a limited acception of vars... *
- * 06Jun91 KvGend Loop & Until implemented *
- *par10 27Jul91 KvGend Skip & EndSkip, and many other improvements*
- *par11 11Aug91 KvGend implemented Text (finally) *
- * 27Aug91 KvGend Anim. Not implemented, just added *
- ****************************************************************/
- #define PARSER
-
- #include <exec/types.h>
- #include "uni4.h" /* the ChemNiMate include */
-
- extern char header[];
- extern char footer[];
-
- extern int array[MXNUMB][8];
-
-
- extern char *tlist[];
- extern struct DisplayInfo di;
-
- int values[VALUESMAX]; /*array with return-values */
- struct ParserInfo pi =
- {0, 1, 0, -1, FALSE, 0, 0};
-
- /***********************prototypes**********/
- extern LetItShow (int, int, int);
- int rightnr (int, int);
-
- /************************int parser(char *)***/
- int
- parser (char *regel, int listnr)
- {
- int i, j, strcount = 0, token;
-
- /******** Tokenizing******/
- token = tlist[listnr][0] & 0xFF;
- pi.valnr = getvalues (regel, values); /*get values in the line */
-
- pi.error = -1;
- if (token != 0) /* check right number of arguments */
- rightnr (pi.valnr, tlist[listnr][1] & 0x0f);
-
- if (pi.skip == TRUE)
- { /*handle a skip */
- if (token == 0x46)
- pi.skip = FALSE;
- return (0);
- }
-
- /********************* interpreting ******************/
- if (pi.error == -1)
- switch (token)
- {
- case 0: /*no token available */
- if (pi.datanr) /***** data-line ? *****/
- {
- if (pi.valnr != 5)
- {
- pi.error = DATA_ERR;
- break;
- }
- for (i = 0; i < 5; i++)
- array[pi.datanr][i] = values[i];
- pi.datanr++;
- break;
- }
- pi.error = HEADACHE_ERR;/***** no, headache (==Syntax Error) *****/
- break;
-
- case 0x10: /***** data *****/
- pi.datanr = values[0];
- if (pi.datanr == 0 || pi.datanr >= MXNUMB)
- pi.error = VAL_ERR;
- break;
-
- case 0x11: /***** EndData *****/
- if (pi.datanr != 0)
- pi.datanr = 0;
- else
- pi.error = EDWD_ERR;
- break;
-
- case 0x12:
- printf ("==> ANIM command used... auto-config to MeSsyDOS NOT IMPLEMENTED YET\n");
- break;
-
- case 0x20: /***** Repeat *****/
- i = 0;
- if (values[0] <= 1)
- pi.error = VAL_ERR;
- else
- i = values[0] + 1024 * pi.linenr;
- /* throw the repeatpos on the stack */
- stack (ST_PUSH, ST_REPEAT, i);
- break;
-
- case 0x21: /***** EndRepeat *****/
- i = stack (ST_POP, ST_REPEAT, 0);
- if (i != ST_NOST) /* there was a repeat on the stack*/
- {
- if (i % 1024 > 1)
- {
- pi.linenr = i / 1024; /* restore to linenr */
- stack (ST_PUSH, ST_REPEAT, --i); /* and put it back where it belongs*/
- }
- break;
- }
- pi.error = ERWR_ERR;
- break;
-
- case 0x22: /***** Loop *****/
- /* throw the repeatpos on the stack */
- stack (ST_PUSH, ST_LOOP, pi.linenr * 1024 + 0);
- break;
-
- case 0x23: /***** Until <1> >= <2> *****/
- i = stack (ST_POP, ST_LOOP, 0);
- if (i == ST_NOST)
- {
- pi.error = ERWR_ERR;
- break;
- }
- if (i % 1024 >= INFINITYMAX)
- {
- pi.error = INFINITY_ERR;
- break;
- }
- if (values[0] < values[1])
- {
- pi.linenr = i / 1024;
- stack (ST_PUSH, ST_LOOP, ++i);
- }
- break;
-
- case 0x30: /***** Lines on/off*****/
- switch (values[0])
- {
- case ON:
- di.modes |= LINES; /* turn lines on */
- break;
- case OFF:
- di.modes &= ~LINES; /* turn lines off */
- break;
- default:
- pi.error = VAL_ERR;
- }
- break;
-
- case 0x31: /***** Balls On/Off *****/
- switch (values[0])
- {
- case ON:
- di.modes |= BALLS;
- break;
- case OFF:
- di.modes &= ~BALLS;
- break;
- default:
- pi.error = VAL_ERR;
- }
- break;
-
- case 0x32: /***** wait time *****/
- for (i = 0; i < values[0]; i++)
- WAITFRAME ();
- break;
-
- case 0x34: /***** DISPLAYMODE *****/
- if (values[0] != 0 && values[0] != 1)
- {
- pi.error = VAL_ERR;
- break;
- }
- di.modes &= ~31;
- di.modes |= values[0] & 31;
- break;
-
- case 0x41: /***** DEBUG *****/
- for (i = values[0]; i <= values[1]; i++)
- {
- printf ("\n%3d: ", i);
- for (j = 0; j < 8; j++)
- printf ("%4d ", array[i][j]);
- }
- printf ("\n");
- break;
-
- case 0x45: /***** Skip *****/
- pi.skip = TRUE;
- break;
- case 0x46: /***** EndSkip *****/
- pi.error = NOSKIP_ERR; /* when the program ever gets here, */
- break; /* it means that there isn't a SKIP encountered */
-
- case 0x50: /***** Show *****/
- if (values[2] < values[1] || values[0] < 1)
- pi.error = VAL_ERR;
- else
- LetItShow (values[0], values[1], values[2]);
- break;
-
- case 0x51: /***** ShowNS *****/
- if (values[1] < values[0])
- pi.error = VAL_ERR;
- else
- LetItShow (0, values[0], values[1]);
- break;
-
- case 0x52: /* SPages */
- SwapShow ();
- break;
-
- case 0x62: /***** Set MiddleOfScreen (oorsprong)*****/
- if (values[0] > VWIDTH || values[0] < 0 || values[1] > VHEIGHT || values[1] < 0)
- {
- pi.error = VAL_ERR;
- break;
- }
- di.mx = values[0] + LBOR;
- di.my = values[1] + UBOR;
- break;
-
- case 0x70: /***** THeader *****/
- TakeStr (regel, header);
- break;
- case 0x71: /***** TFooter *****/
- TakeStr (regel, footer);
- break;
- case 0x72:
- if (values[0] > VWIDTH || values[0] < 0 || values[1] > VHEIGHT || values[1] < 0)
- {
- pi.error = VAL_ERR;
- break;
- }
- TakeStr (regel, regel);
- TextAt (values[0], values[1], regel);
- break;
- case 0x73: /***** T *****/
- TakeStr (regel, regel);
- printf ("#tekst: '%s'\n", regel);
- break;
-
- case 0x80: /***** change *****/
- case 0x81:
- case 0x82:
- DoChange (regel, token);
- break;
-
- case 0x90: /***** I:= *****/
- pi.I = values[0];
- break;
- case 0x91: /***** J:= *****/
- pi.J = values[0];
- break;
- case 0x92:
- case 0x60: /***** ANG:= *****/
- di.angle = (values[0] & 63) + 65536;
- break;
- case 0x93:
- case 0x61: /***** DAN:= *****/
- if (values[0] > 10 || values[0] < -10)
- pi.error = VAL_ERR;
- else
- di.dangle = values[0];
- break;
-
- default:
- printf ("$$ This should not occur !!!\nToken : %X Line : %d\n", token, pi.linenr);
- }
- if (pi.error == -1) /*no error */
- return (0);
- /*an error occurred */
- ErrHand (pi.error, pi.linenr);
- } /**************end-of-parser()*/
-
-
-
- ErrHand (int which, int nr) /* fout-afhandeling */
- {
- /* I designed it this way, to keep the error messages issued from one point*/
- printf ("%s IN LINE %d\n", errtxt[which], nr);
- }
-
-
- /****************************getvalues(char *line,int *values) *****/
- int
- getvalues (char *line, int *values)
- {
- int i = 0, j = 0, q;
-
- /* scan until first value or ;(remark) or ](end-of-expr)*/
- for (j = 0; j < strlen (line); j++)
- {
- if (line[j] == '#') /*begin of a variable */
- {
- q = gvar (line + j + 1);
- if ((values[i++] = q) == FULLCRAZY)
- return (-1);
- while (line[++j] != '#') ; /*continue till end of varname */
- continue;
- }
- if (line[j] == '[') /*begin of an expression */
- {
- q = evalexp (line + j + 1);
- if ((values[i++] = q) == FULLCRAZY)
- return (-1); /*error in evaluating*/
- while (line[j] != '@')
- j++;
- line[j] = '©';
- }
- if (ISNUM (line[j]))
- { /* it's a value !!*/
- values[i++] = atoi (&line[j]);
- if (i >= VALUESMAX)
- break;
- while (ISNUM (line[j]))
- j++;
- j--;
- }
- /* stop with getvalues when: */
- if (line[j] == ';' || line[j] == '\"' || line[j] == ']')
- break;
- }
- return (i);
- }
-
- char *vars[] =
- {"I\0", "J\0", "ON\0", "OFF\0", "ANG\0", "DAN\0", "#"};
-
- /*******************************int gvar(char *line) *****/
- int
- gvar (char *line)
- {
- char name[8];
- int teller = 0, welke;
-
- for (teller = 0; line[teller] != '#' && teller < 3; teller++)
- name[teller] = line[teller];/* copy 'line' in 'name' */
- name[teller] = 0; /* null-terminate string*/
-
- if (teller > 3)
- {
- pi.error = VAREND_ERR;
- return (FULLCRAZY);
- }
- for (welke = 0; vars[welke][0] != '#'; welke++)
- if (!strcmp (name, vars[welke]))
- break;
- if (vars[welke][0] == '#')
- {
- pi.error = NOVAR_ERR;
- return (FULLCRAZY); /*not a right name*/
- }
- switch (welke)
- {
- case 0: /* I */
- return (pi.I);
- case 1: /* J */
- return (pi.J);
- case 2: /* ON */
- return (ON);
- case 3: /* OFF */
- return (OFF);
- case 4: /* ANG */
- return (di.angle & 63);
- case 5: /* DAN */
- return (di.dangle & 63);
- }
- printf ("this should not occur: welke: %d\n", welke);
- return (FULLCRAZY); /*HELP!! WE SHOULD NEVER GET THIS FAR!!*/
- } /*end-of-gvar() */
-
-
- /*******************************int evalexp(char *line) *****/
- int
- evalexp (char *line)
- {
- int data[VALUESMAX];
- int teller, result = FULLCRAZY;
-
- if (getvalues (line, data) == 2)
- {
- for (teller = 0; teller < strlen (line) && result == FULLCRAZY; teller++)
- switch (line[teller])
- {
- case '*':
- result = data[0] * data[1];
- break;
- case '/':
- if (data[1] == 0)
- {
- pi.error = DIVISION_ERR;
- return (FULLCRAZY);
- }
- result = data[0] / data[1];
- break;
- case '+':
- result = data[0] + data[1];
- break;
- case '_':
- result = data[0] - data[1];
- break;
- } /* end-of-switch() */
- /* remove the operator */
- if (result != FULLCRAZY)
- line[teller - 1] = '$';
- else
- pi.error = ITTAKESTWO_ERR; /*shit! no operator*/
- /* check and remove the ] */
- for (teller = 0; line[teller] != ']' && teller < strlen (line); teller++) ;
- if (line[teller] != ']')
- {
- pi.error = PARENTH_ERR;
- result = FULLCRAZY;
- }
- line[teller] = '@';
- } /*end-of-if*/
- else
- /*not right number of values */
- pi.error = ITTAKESTWO_ERR;
- return (result);
- } /*End-Of-evalexp() */
-
- /**************************TakeStr(char *line,char *desstr)**/
- TakeStr (char *line, char *desstr)
- {
- int teller = 0, pos = 0;
- do
- {
- pos++;
- } while (pos <= strlen (line) && line[pos - 1] != '\"');
- do
- {
- desstr[teller++] = line[pos++];
- } while (pos <= strlen (line) && line[pos] != '\"');
- desstr[teller] = 0;
- }
-
- /**************************rightnr(real number,required number)*****/
- int
- rightnr (int realnr, int reqnr)
- {
- if (realnr < reqnr)
- {
- pi.error = TOOFEW_ERR;
- errtxt[pi.error][27] = realnr + '0';
- errtxt[pi.error][10] = reqnr + '0';
- return (1); /* ERROR, line is not executable */
- }
- if (realnr > reqnr)
- {
- pi.error = TOOMUCH_ERR;
- errtxt[pi.error][31] = reqnr + '0';
- return (1); /* ERROR, line is not executable */
- }
- return (0); /* wow, right number of values */
- }
-
-
- /***********************************DoChange(regel)***********
- * The change-group (0x80 - 0x8f)
- * C Change
- * [R] relative <nr> <type> <add>
- * [A] absolute <nr> <type> <value>
- * [M] more items relative <from> <upto&including> <type> <add>
- */
- DoChange (char *regel, int token)
- {
- int i;
-
- switch (token)
- {
- case 0x80:
- case 0x81:
- if (values[1] > 4 || values[1] < 0
- || values[0] < 0 || values[0] >= MXNUMB)
- pi.error = VAL_ERR;
- else if (token == 0x80)
- array[values[0]][values[1]] += values[2]; /* relative ch. */
- else
- array[values[0]][values[1]] = values[2]; /*absolute change */
- break;
-
- case 0x82:
- if (values[1] <= values[0]
- || values[0] < 0
- || values[1] >= MXNUMB
- || values[2] < 0 || values[2] > 4)
- pi.error = VAL_ERR; /*INCORRECT VALUE */
- else
- for (i = values[0]; i <= values[1]; i++)
- array[i][values[2]] += values[3];
- break;
-
- default:
- pi.error = HEADACHE_ERR;
- }
- }
-
- /**********************************int stack(int code,int value)***
- *calling:
- * stack(ST_PUSH,id,value) id=(depth+id) of repeat/gosub etc.
- * value = stack(ST_POP,id,0); get the value of the stack which represents
- * the id (nb: depth is ignored)
- * value = stack(ST_QUIT,0,0); if !0, there's garbage on the stack.
- *
- */
- int
- stack (int code, int type, long int value)
- {
- static int stack[STMAX][2];
- static int stkptr = 0;
- long int ret;
- int tel;
-
- switch (code)
- {
- case ST_INIT: /* just for symmetry (Teijo, thanks for excuse)*/
- break;
- case ST_PUSH: /* push something on the stack*/
- if (stkptr < STMAX)
- {
- stack[++stkptr][0] = type;
- stack[stkptr][1] = value;
- }
- break;
- case ST_POP:
- if (stkptr > 0) /* IS there a stack */
- {
- for (tel = stkptr; tel > 0; tel--) /* yes, there is a stack */
- if (stack[tel][0] == type)
- {
- ret = stack[tel][1];
- stkptr = tel - 1; /* decrease the stkptr -> point to prev */
- break; /* break the for */
- }
- if (tel == 0) /* unfortunately, there's not what we want */
- ret = ST_NOST;
- } /* end-of-if */
- else
- ret = ST_NOST; /* no, there ain't a stack */
- break;
- case ST_QUIT: /* it is wrong when !0 returned */
- ret = stkptr;
- break;
- }
- return (ret);
- }
-